package ar.edu.ufasta.presupuestos.logica.aplicativo;

import java.sql.ResultSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import ar.edu.ufasta.presupuestos.logica.entidades.Fabrica;
import ar.edu.ufasta.presupuestos.logica.entidades.Proveedor;
import ar.edu.ufasta.presupuestos.logica.entidades.articulo.Articulo;
import ar.edu.ufasta.presupuestos.logica.entidades.articulo.ArticuloComplejo;
import ar.edu.ufasta.presupuestos.logica.entidades.articulo.ArticuloSimple;
import ar.edu.ufasta.presupuestos.logica.entidades.articulo.DetalleArticulo;
import ar.edu.ufasta.presupuestos.logica.entidades.articulo.Servicio;
import ar.edu.ufasta.presupuestos.logica.entidades.articulo.TipoArticulo;
import ar.edu.ufasta.presupuestos.servicios.ConexionMySQL;
import ar.edu.ufasta.presupuestos.servicios.inventario.InventarioFacade;
import ar.edu.ufasta.presupuestos.servicios.persistencia.ObjectID;
import ar.edu.ufasta.presupuestos.servicios.persistencia.PersistenceFacade;

/**
 * Clase que realiza la logica de la interfaz visual del aplicativo Seccion
 * Articulos: - Listado de articulos - Busqueda de 1 articulo - Alta de articulo -
 * Baja de articulo - Modificacion de articulo
 * 
 * @author Carlos Gaspar
 * @version 0.0.0.1 Universidad FASTA
 * 
 */
public class ControladorSeccionArticulos extends ControladorGenerico {

	// private Logger log = Logger.getLogger(name);
	public Articulo miArticulo;
	public String proveedor;// para esta iteracion
	public String fabrica;// para esta iteracion

	private Hashtable<String, Object> parametros;

	// private Vector<Object> listadoFabricas; // private Vector<Fabrica>
	// listadoFabricas

	/**
	 * Encontrar todos los registros almacenados ordenados segun una condicion
	 * WHERE
	 * 
	 * @param tabla ->
	 *            Nombre de la tabla a usar
	 * @param ordenLista ->
	 *            Orden en que se devolvera la lista
	 * @param condicion ->
	 *            Condicion a utilizar al seleccionar los datos
	 * @return Lista de entradas encontradas
	 * @throws Exception
	 * 
	 */
	public Vector<Object[]> getRegistrosDonde(int tipo, String tabla,
			String ordenLista, int condicion) throws Exception {
		Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		switch (tipo) {
		case 1: // Articulos
			vec = buscarArticulos(tabla, ordenLista, condicion);
			break;
		case 2: // Proveedores
			vec = buscarDistribuidores(tabla, ordenLista, condicion);
			break;
		case 3: // Fabricas
			vec = buscarDistribuidores(tabla, ordenLista, condicion);
			break;
		case 4: // Detalle de un articulo
			vec = buscarDetalleArticulo(tabla, ordenLista, condicion);
		default:
			break;
		}
		// return myList;
		return vec;
	}

	private Vector<Object[]> buscarDetalleArticulo(String tabla,
			String ordenLista, int condicion) {
		Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		int articuloCode=0;
		Articulo art;
		ArticuloComplejo miAComplejo;
		InventarioFacade inventario = InventarioFacade.getInstancia();
		miAComplejo = (ArticuloComplejo)inventario.getArticulo(new ObjectID(condicion));
		
		// Devulevo arreglo de valores a la vista
		for (DetalleArticulo detalle : miAComplejo.getDetalle()) {
			articuloCode = detalle.getArticulo().getIDValue();
			// Obtengo info del articulo
			art = inventario.getArticulo(new ObjectID(articuloCode));
			
			Object[] record = new Object[6];
			record[0] = art.getNombre();
			record[1] = art.getCostoUnitario();
			record[2] = detalle.getCantidad();
			Double total = art.getCostoUnitario() * detalle.getCantidad();
			record[3] = total;
			record[4] = articuloCode;
			record[5] = detalle.getIDValue();
			vec.addElement(record);
		}
		return vec;
	}

	private Vector<Object[]> buscarArticulos(String tabla, String ordenLista,
			int condicion) throws Exception {
		Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		List<Articulo> lista;
		try {
			InventarioFacade inventario = InventarioFacade.getInstancia();
			lista = inventario.getAllArticulo();

			for (Articulo articulo : lista) {
				Object[] record = new Object[7];
				record[0] = articulo.getIDValue();
				record[1] = articulo.getNombre();
				record[2] = articulo.getDescripcion();
				record[3] = articulo.getCosto();
				record[4] = articulo.getCantidad();
				record[5] = articulo.getCostoUnitario();
				record[6] = articulo.getTipoArticulo();
				vec.addElement(record);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return vec;
	}

	private Vector<Object[]> buscarDistribuidores(String tabla,
			String ordenLista, int condicion) throws Exception {
		Vector<Object[]> vec;
		vec = new Vector<Object[]>();
		try {
			ConexionMySQL conn = ConexionMySQL.getInstancia();
			String zQuery = null;
			zQuery = "SELECT * FROM " + tabla;
			//if (condicion != null)
			//	zQuery += "WHERE " + condicion;
			if (ordenLista != null)
				zQuery += "ORDER BY " + ordenLista;
			ResultSet resulset = conn.executeQuery(zQuery);

			while (resulset.next()) {
				Object[] record = new Object[2];
				record[0] = resulset.getInt("ID");
				record[1] = resulset.getString("Nombre");
				vec.addElement(record);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return vec;
	}

	/**
	 * Encuentra un articulo y todos sus elementos relacionados
	 * 
	 * @param code -> ID del articulo a traer de la base de datos
	 * @return void
	 * @throws Exception
	 * 
	 */
	public Hashtable<String, Object> consultaArticulo(String code)
			throws Exception {
		Hashtable<String, Object> articuloMap = new Hashtable<String, Object>();
		Articulo articuloAct;
		Proveedor proveedorTemp;
		Fabrica fabricaTemp;
		Object[] recordProveedor;
		Object[] recordFabrica;
		try {
			int tipo;
			InventarioFacade inventario = InventarioFacade.getInstancia();
			articuloAct = inventario.getArticulo(new ObjectID(Integer
					.valueOf(code)));
			tipo = articuloAct.getTipoArticulo().getIDValue();

			switch (tipo) {
			case 1:
				articuloMap.put("vStock", articuloAct.getCantidad());
				articuloMap.put("vStockMinimo", articuloAct.getCantidadMinima());
				proveedorTemp = articuloAct.getProveedor();
				recordProveedor = new Object[2];
				if (proveedorTemp != null){
					recordProveedor[0] = proveedorTemp.getIDValue();
					recordProveedor[1] = proveedorTemp.getNombre();
				}else{
					recordProveedor[0] = -1;
					recordProveedor[1] = "NaN";
				}
				fabricaTemp = articuloAct.getFabrica();
				recordFabrica = new Object[2];
				if (fabricaTemp != null){
					recordFabrica[0] = fabricaTemp.getIDValue();
					recordFabrica[1] = fabricaTemp.getNombre();
				}else{
					recordFabrica[0] = -1;
					recordFabrica[1] = "NaN";
				}
				articuloMap.put("vProveedor", (Object[]) recordProveedor);
				articuloMap.put("vFabrica", (Object[])recordFabrica);				
				break;
			case 2:
				articuloMap.put("vStock", articuloAct.getCantidad());
				articuloMap.put("vStockMinimo", articuloAct.getCantidadMinima());
				fabricaTemp = articuloAct.getFabrica();
				recordFabrica = new Object[2];
				if (fabricaTemp != null){
					recordFabrica[0] = fabricaTemp.getIDValue();
					recordFabrica[1] = fabricaTemp.getNombre();
				}else{
					recordFabrica[0] = -1;
					recordFabrica[1] = "NaN";
				}
				articuloMap.put("vFabrica", recordFabrica);
				// Get Lista de componentes
				break;
			case 3:
				break;
			default:
				break;
			}
			articuloMap.put("vIDArticulo", articuloAct.getIDValue());
			articuloMap.put("vNombre", articuloAct.getNombre());
			articuloMap.put("vTipo", articuloAct.getTipoArticulo());
			articuloMap.put("vDescripcion", articuloAct.getDescripcion());
			articuloMap.put("vPrecio", articuloAct.getCosto());
			articuloMap.put("vPrecioUnitario", articuloAct.getCostoUnitario());

		} catch (Exception e) {
			e.printStackTrace();
		}
		return articuloMap;
	}

	/**
	 * Inserta un nuevo articulo en la base de datos
	 * 
	 * @param params ->
	 *            Parametros del nuevo articulo a insertar
	 * @return void
	 * @throws Exception
	 * 
	 */
	public int insertaArticulo(String nombrePK, Hashtable<String, Object> params, Vector<Object[]> items) {
		Boolean resul_val;
		int ret;
		int fabrica;
		int proveedor;
		Fabrica fabricaTemp;
		Proveedor proveedorTemp;
		this.parametros = params;

		int id_producto;
		int cantidad;
		Integer quantity = 0;
		PersistenceFacade pf = PersistenceFacade.getInstance();
		// Tipo de articulo a insertar
		switch ((Integer) parametros.get("vTipo")) {
		case 1:
			miArticulo = new ArticuloSimple();
			//miArticulo.setOid(new ObjectID(-1));
			miArticulo.setTipoArticulo((TipoArticulo) pf.get(new ObjectID(1), TipoArticulo.class));
			miArticulo.setNombre((String) parametros.get("vNombre"));
			miArticulo.setDescripcion((String) parametros.get("vDescripcion"));
			miArticulo.setCosto((Double) parametros.get("vPrecio"));
			miArticulo.setCostoUnitario((Double) parametros.get("vPrecioUnitario"));
			miArticulo.setCantidadMinima((Integer)parametros.get("vStockMinimo"));
			quantity =  (Integer) parametros.get("vStock");
			fabrica = (Integer)parametros.get("vFabricaID");
			proveedor = (Integer)parametros.get("vProveedorID");
			if (fabrica != -1){
				fabricaTemp = new Fabrica();
				fabricaTemp.setOid(new ObjectID(fabrica));
				miArticulo.setFabrica(fabricaTemp);
			}else{
				proveedorTemp = new Proveedor();
				proveedorTemp.setOid(new ObjectID(proveedor));
				miArticulo.setProveedor(proveedorTemp);
			}
			break;
		case 2:
			miArticulo = new ArticuloComplejo();
			//miArticulo.setOid(new ObjectID(0));
			miArticulo.setTipoArticulo((TipoArticulo) pf.get(new ObjectID(2), TipoArticulo.class));
			miArticulo.setNombre((String) parametros.get("vNombre"));
			miArticulo.setDescripcion((String) parametros.get("vDescripcion"));
			miArticulo.setCosto((Double) parametros.get("vPrecio"));
			miArticulo.setCostoUnitario((Double) parametros.get("vPrecioUnitario"));
			miArticulo.setCantidadMinima((Integer)parametros.get("vStockMinimo"));
			quantity = (Integer) parametros.get("vStock");
			fabrica = (Integer)parametros.get("vFabricaID");
			fabricaTemp = new Fabrica();
			fabricaTemp.setOid(new ObjectID(fabrica));
			miArticulo.setFabrica(fabricaTemp);
			for (Iterator<Object[]> iterator = items.iterator(); iterator.hasNext();) {
				Object[] objects = (Object[]) iterator.next();
				id_producto = (Integer)objects[4];
				cantidad = (Integer)objects[2];
				
				((ArticuloComplejo) miArticulo).agregarNuevoDetalle(id_producto,cantidad,-1);
			}
			break;
		case 3:
			miArticulo = new Servicio();
			//miArticulo.setOid(new ObjectID(0));
			miArticulo.setTipoArticulo((TipoArticulo) pf.get(new ObjectID(3), TipoArticulo.class));
			miArticulo.setNombre((String) parametros.get("vNombre"));
			miArticulo.setDescripcion((String) parametros.get("vDescripcion"));
			miArticulo.setCosto((Double) parametros.get("vPrecio"));
			break;
		default:
			System.out.println("Error en tipo de articulo");
			return -1;
		}
		InventarioFacade inventario = InventarioFacade.getInstancia();
		resul_val = inventario.addArticulo(miArticulo, quantity);
		if (resul_val == true)
			ret = 0;
		else
			ret = -1;
		return ret;
	}

	/**
	 * Elimina un articulo de la base de datos
	 * 
	 * @param params -> ID del articulo a traer de la base de datos
	 * @return void
	 * @throws Exception
	 * 
	 */
	public int eliminaArticulo(Hashtable<String, Object> params) {
		Boolean resul_val;
		int ret;
		this.parametros = params;
		//TODO Validacion -> tiene presupuestos asociados
		
		// Chequeo si el articulo no tiene presupuestos o articulos asociados
		// Tipo de articulo a insertar
		switch ((Integer) parametros.get("vTipo")) {
		case 1:
			miArticulo = new ArticuloSimple();
			miArticulo.setOid(new ObjectID((Integer) parametros
					.get("vIDArticulo")));
			break;
		case 2:
			miArticulo.setOid(new ObjectID((Integer) parametros
					.get("vIDArticulo")));
			break;
		case 3:
			miArticulo = new Servicio();
			miArticulo.setOid(new ObjectID((Integer) parametros
					.get("vIDArticulo")));
			break;
		default:
			System.out.println("Error en tipo de articulo");
			return -1;
		}
		InventarioFacade inventario = InventarioFacade.getInstancia();
		resul_val = inventario.removeArticulo(miArticulo.getOid()); 
		if (resul_val == true)
			ret = 0;
		else
			ret = -1;
		return ret;
	}

	/**
	 * Modifica un articulo existente en la base de datos
	 * 
	 * @param params -> ID del articulo a traer de la base de datos
	 * @return void
	 * @throws Exception
	 * 
	 */
	public int actualizaArticulo(Hashtable<String, Object> params, Vector<Object[]> items) {
		int fabrica;
		int proveedor;
		Boolean resul_val;
		int ret;
		Fabrica fabricaTemp;
		Proveedor proveedorTemp;
		this.parametros = params;
		Integer quantity = 0;
		// Tipo de articulo a modificar
		switch ((Integer) parametros.get("vTipo")) {
		case 1:
			miArticulo = new ArticuloSimple();
			miArticulo.setOid(new ObjectID((Integer) parametros
					.get("vIDArticulo")));
			miArticulo.setNombre((String) parametros.get("vNombre"));
			miArticulo.setDescripcion((String) parametros.get("vDescripcion"));
			miArticulo.setCosto((Double) parametros.get("vPrecio"));
			miArticulo.setCostoUnitario((Double) parametros.get("vPrecioUnitario"));
			miArticulo.setCantidadMinima((Integer)parametros.get("vStockMinimo"));
			quantity = (Integer) parametros.get("vStock");
			fabrica = (Integer)parametros.get("vFabricaID");
			proveedor = (Integer)parametros.get("vProveedorID");
			if (fabrica != -1){
				fabricaTemp = new Fabrica();
				fabricaTemp.setOid(new ObjectID(fabrica));
				miArticulo.setFabrica(fabricaTemp);
			}else{
				proveedorTemp = new Proveedor();
				proveedorTemp.setOid(new ObjectID(proveedor));
				miArticulo.setProveedor(proveedorTemp);
			}
			break;
		case 2:
			miArticulo = new ArticuloComplejo();
			miArticulo.setOid(new ObjectID((Integer) parametros.get("vIDArticulo")));
			miArticulo.setNombre((String) parametros.get("vNombre"));
			miArticulo.setDescripcion((String) parametros.get("vDescripcion"));
			miArticulo.setCosto((Double) parametros.get("vPrecio"));
			miArticulo.setCostoUnitario((Double) parametros.get("vPrecioUnitario"));
			miArticulo.setCantidadMinima((Integer)parametros.get("vStockMinimo"));
			quantity = (Integer) parametros.get("vStock");
			fabrica = (Integer)parametros.get("vFabricaID");
			fabricaTemp = new Fabrica();
			fabricaTemp.setOid(new ObjectID(fabrica));
			miArticulo.setFabrica(fabricaTemp);
			for (Iterator<Object[]> iterator = items.iterator(); iterator.hasNext();) {
				Object[] objects = (Object[]) iterator.next();
				Integer id_producto = (Integer)objects[4];
				Integer cantidad = (Integer)objects[2];
				Integer id_detalle = (Integer) objects[5];
				((ArticuloComplejo) miArticulo).agregarNuevoDetalle(id_producto,cantidad,id_detalle);
			}
			break;
		case 3:
			miArticulo = new Servicio();
			miArticulo.setOid(new ObjectID((Integer) parametros
					.get("vIDArticulo")));
			miArticulo.setNombre((String) parametros.get("vNombre"));
			miArticulo.setDescripcion((String) parametros.get("vDescripcion"));
			miArticulo.setCosto((Double) parametros.get("vPrecio"));
			break;
		default:
			System.out.println("Error en tipo de articulo");
			return -1;
		}
		InventarioFacade inventario = InventarioFacade.getInstancia();
		resul_val = inventario.updateArticulo(miArticulo,quantity);
		if (resul_val == true)
			ret = 0;
		else
			ret = -1;
		return ret;
	}

	public void finalizar() {

	}
}
